﻿// Decompiled with JetBrains decompiler
// Type: Netick.SequenceId
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System.Collections.Generic;

#nullable disable
namespace Netick;

/// <summary>
/// A rolling sequence counter for ordering values. Repeats indefinitely
/// with 1022 possible unique values (0 is treated as invalid internally).
/// 
/// Consumes 10 bits when encoded for transmission.
/// </summary>
internal struct SequenceId
{
  public static readonly IEqualityComparer<SequenceId> Comparer = (IEqualityComparer<SequenceId>) new SequenceId.SequenceIdComparer();
  private const int BITS_USED = 26;
  private const int MAX_VALUE = 67108863 /*0x03FFFFFF*/;
  private const int HALF_WAY_POINT = 33554431 /*0x01FFFFFF*/;
  private const int BIT_SHIFT = 6;
  public static readonly SequenceId INVALID = new SequenceId(0U);
  public static readonly SequenceId START = new SequenceId(1U);
  public readonly uint RawValue;

  private static int GetDifference(SequenceId a, SequenceId b)
  {
    return ((int) a.RawValue << 6) - ((int) b.RawValue << 6);
  }

  private static int WrapValue(int rawValue)
  {
    if (rawValue > 67108863 /*0x03FFFFFF*/)
      return rawValue % 67108863 /*0x03FFFFFF*/;
    return rawValue < 1 ? rawValue % 67108863 /*0x03FFFFFF*/ + 67108863 /*0x03FFFFFF*/ : rawValue;
  }

  public static SequenceId operator +(SequenceId a, int b)
  {
    return new SequenceId((uint) SequenceId.WrapValue((int) a.RawValue + b));
  }

  public static SequenceId operator -(SequenceId a, int b)
  {
    return new SequenceId((uint) SequenceId.WrapValue((int) a.RawValue - b));
  }

  public static int operator -(SequenceId a, SequenceId b)
  {
    int num = SequenceId.GetDifference(a, b) >> 6;
    if (a.RawValue < b.RawValue)
    {
      if (num > 0)
        --num;
    }
    else if (num < 0)
      ++num;
    return num;
  }

  public static SequenceId operator ++(SequenceId a) => a.Next;

  public static bool operator >(SequenceId a, SequenceId b) => SequenceId.GetDifference(a, b) > 0;

  public static bool operator <(SequenceId a, SequenceId b) => SequenceId.GetDifference(a, b) < 0;

  public static bool operator >=(SequenceId a, SequenceId b) => SequenceId.GetDifference(a, b) >= 0;

  public static bool operator <=(SequenceId a, SequenceId b) => SequenceId.GetDifference(a, b) <= 0;

  public static bool operator ==(SequenceId a, SequenceId b)
  {
    return (int) a.RawValue == (int) b.RawValue;
  }

  public static bool operator !=(SequenceId a, SequenceId b)
  {
    return (int) a.RawValue != (int) b.RawValue;
  }

  public SequenceId Next
  {
    get
    {
      uint rawValue = this.RawValue + 1U;
      if (rawValue > 67108863U /*0x03FFFFFF*/)
        rawValue = 1U;
      return new SequenceId(rawValue);
    }
  }

  public bool IsValid => this.RawValue > 0U;

  internal SequenceId(uint rawValue) => this.RawValue = rawValue;

  public override int GetHashCode() => (int) this.RawValue;

  public override bool Equals(object obj)
  {
    return obj is SequenceId sequenceId && (int) sequenceId.RawValue == (int) this.RawValue;
  }

  public override string ToString()
  {
    return this.IsValid ? "SequenceId:" + (this.RawValue - 1U).ToString() : "SequenceId:INVALID";
  }

  internal class SequenceIdComparer : IEqualityComparer<SequenceId>
  {
    public bool Equals(SequenceId x, SequenceId y) => x == y;

    public int GetHashCode(SequenceId x) => x.GetHashCode();
  }
}
